#include <QtCore>
#include <QtGui>
#include <QtNetwork>

#define _WIN32_WINNT	0x0600

#include <windows.h>

#include "WinRemocon.h"
#include "WinRemoconProtocol.h"

WinRemocon::WinRemocon(QWidget *parent): QDialog(parent)
{
	ui.setupUi(this);
	setupKeyMaps();

	// settings
	if (QFileInfo(qApp->applicationName() + ".ini").exists())
		settings = new QSettings(qApp->applicationName() + ".ini", QSettings::IniFormat, this);
	else
		settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, qApp->organizationName(), qApp->applicationName(), this);

	// log
	ui.enableLog->setChecked(settings->value("Log/enable").toBool());
	ui.logLevel->setCurrentIndex(settings->value("Log/level").toInt());
	connect(ui.saveLog, SIGNAL(clicked()), this, SLOT(saveLog()));
	connect(ui.clearLog, SIGNAL(clicked()), ui.log, SLOT(clear()));

	// port
	ui.port->setValue(settings->value("General/port", DEFAULT_PORT).toInt());
	connect(ui.portSetButton, SIGNAL(clicked()), this, SLOT(changePort()));

	// event delay
	ui.clickDelay->setValue(settings->value("Event/event_delay", 10).toInt());

	// mouse accelerator
	ui.mouseAccel->setValue(settings->value("Event/mouse_accel", 1.0).toDouble());

		// event diabler
		ui.disableAllEvents->setChecked(settings->value("Event/disable_all_events", false).toBool());
		ui.disableMouseEvents->setChecked(settings->value("Event/disable_mouse_events", false).toBool());
		ui.disableKeyboardEvents->setChecked(settings->value("Event/disable_keyboard_events", false).toBool());

	// allowed list
	ui.notifyOnNewClient->setChecked(settings->value("Client/notify_on_new_client", true).toBool());
	ui.allowAllClients->setChecked(settings->value("Client/allow_all_clients", false).toBool());
	ui.allowedList->addItems(settings->value("Client/allowed").toStringList());
	connect(ui.allowClient, SIGNAL(clicked()), this, SLOT(allowClient()));
	connect(ui.denyClient, SIGNAL(clicked()), this, SLOT(denyClient()));

	// hardware
	ui.keyboardType->setCurrentIndex(settings->value("Hardware/keyboard_type", 0).toInt());

	// startup
	connect(ui.startupCurrentUser, SIGNAL(toggled(bool)), this, SLOT(toggleStartupCurrentUser(bool)));
	connect(ui.startupAllUsers, SIGNAL(toggled(bool)), this, SLOT(toggleStartupAllUsers(bool)));
	checkStartupState();

	// about
	ui.appVersion->setText(qApp->applicationVersion());
	ui.qtVersion->setText(QT_VERSION_STR);

	// socket
	socket = new QUdpSocket(this);
	changePort();
	connect(socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

	// system tray icon
	setupContextMenu();
	trayIcon = new QSystemTrayIcon(this);
	trayIcon->setContextMenu(trayIconMenu);
	trayIcon->setIcon(QIcon(":/icons/Default"));
	trayIcon->setToolTip("WinRemocon");
	trayIcon->setVisible(true);
	connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(show()));
}

WinRemocon::~WinRemocon()
{
	saveSettings();
}

void WinRemocon::saveSettings()
{
	settings->setValue("General/port", ui.port->value());

	settings->setValue("Log/enable", ui.enableLog->isChecked());
	settings->setValue("Log/level", ui.logLevel->currentIndex());

	settings->setValue("Event/click_delay", ui.clickDelay->value());
	settings->setValue("Event/mouse_accel", ui.mouseAccel->value());

		settings->setValue("Event/disable_all_events", ui.disableAllEvents->isChecked());
		settings->setValue("Event/disable_mouse_events", ui.disableMouseEvents->isChecked());
		settings->setValue("Event/disable_keyboard_events", ui.disableKeyboardEvents->isChecked());

	settings->setValue("Hardware/keyboard_type", ui.keyboardType->currentIndex());

	settings->setValue("Client/notify_on_new_client", ui.notifyOnNewClient->isChecked());
	settings->setValue("Client/allow_all_clients", ui.allowAllClients->isChecked());
	settings->setValue("Client/allowed_count", ui.allowedList->count());
	{
		QStringList list;
		for (int i = 0; i != ui.allowedList->count(); ++i)
			list.append(ui.allowedList->item(i)->text());
		settings->setValue("Client/allowed", list);
	}
}

void WinRemocon::changePort()
{
	delete socket;
	socket = new QUdpSocket(this);
	int port = ui.port->value();
	if (socket->bind(port, QUdpSocket::DontShareAddress) == false)
		appendLog(tr("Failed to bind port: %1. Please restart this program.").arg(port), LogError);
	else
		appendLog(tr("Port changed to: %1").arg(port), LogDebug);
}

void WinRemocon::setupContextMenu()
{
	trayIconMenu = new QMenu(this);

	QAction *a;

	a = new QAction(tr("&Configuration"), this);
	connect(a, SIGNAL(triggered()), this, SLOT(showNormal()));
	trayIconMenu->addAction(a);

	trayIconMenu->addSeparator();

	a = new QAction(tr("&Quit"), this);
	connect(a, SIGNAL(triggered()), qApp, SLOT(quit()));
	trayIconMenu->addAction(a);
}

void WinRemocon::closeEvent(QCloseEvent *e)
{
	saveSettings();
	hide();
	e->ignore();
}

void WinRemocon::reject()	/* ESC */
{
	hide();
}

void WinRemocon::trayIconActivated(QSystemTrayIcon::ActivationReason)
{
	show();
}

void WinRemocon::allowClient()
{
	if (ui.deniedList->currentItem() == NULL)	return;
	ui.allowedList->addItem(ui.deniedList->takeItem(ui.deniedList->currentRow()));
}

void WinRemocon::denyClient()
{
	if (ui.allowedList->currentItem() == NULL)	return;
	ui.deniedList->addItem(ui.allowedList->takeItem(ui.allowedList->currentRow()));
}

void WinRemocon::appendLog(const QString &s, LogLevel level)
{
	if (!ui.enableLog->isChecked())	return;
	if (level <= ui.logLevel->currentIndex())
		ui.log->appendPlainText(QTime::currentTime().toString("HH:mm:ss: ") + s);
}

void WinRemocon::saveLog()
{
	QString path = QFileDialog::getSaveFileName(this);
	QFile file(path);
	if (file.open(QFile::WriteOnly))
		QTextStream(&file) << ui.log->toPlainText();
}

void WinRemocon::toggleStartupCurrentUser(bool checked)
{
	QSettings userreg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
	if (checked)	userreg.setValue(qApp->applicationName(), QString("\"%1\"").arg(QCoreApplication::applicationFilePath()).replace('/', '\\'));
	else	userreg.remove(qApp->applicationName());
	checkStartupState();
}

void WinRemocon::toggleStartupAllUsers(bool checked)
{
	QSettings sysreg("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
	if (checked)	sysreg.setValue(qApp->applicationName(), QString("\"%1\"").arg(QCoreApplication::applicationFilePath()).replace('/', '\\'));
	else	sysreg.remove(qApp->applicationName());
	checkStartupState();
}

void WinRemocon::checkStartupState()
{
	ui.startupAllUsers->setEnabled(true);
	ui.startupCurrentUser->setEnabled(true);

	QSettings userreg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
	QSettings sysreg("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
	ui.startupCurrentUser->setChecked(userreg.contains(qApp->applicationName()));
	ui.startupAllUsers->setChecked(sysreg.contains(qApp->applicationName()));
	if (ui.startupCurrentUser->isChecked())	ui.startupAllUsers->setEnabled(false);
	if (ui.startupAllUsers->isChecked())	ui.startupCurrentUser->setEnabled(false);
}

void WinRemocon::readPendingDatagrams()
{
	while (socket->hasPendingDatagrams())
	{
		QByteArray data;
		data.resize(socket->pendingDatagramSize());
		QHostAddress sender;
		quint16 senderPort;

		socket->readDatagram(data.data(), data.size(), &sender, &senderPort);

		{	/* debug dump */
			QString hex;
			for (int i = 0; i != data.size(); ++i)
				hex.append(QString(" %1").arg(static_cast<int>(data[i]), 2, 16, QChar('0')));
			appendLog(QString("dump: %1").arg(hex));
		}

		if (ui.allowedList->findItems(sender.toString(), Qt::MatchExactly).count() == 0)
		{
			if (ui.allowAllClients->isChecked())
			{
				appendLog(tr("sender: %1 is automatically allowed").arg(sender.toString()), LogWarn);
				ui.allowedList->addItem(sender.toString());
				if (ui.notifyOnNewClient->isChecked())
					trayIcon->showMessage(qApp->applicationName(), tr("A new client %1 is automatically allowed.").arg(sender.toString()), QSystemTrayIcon::Information, 5000);
				// ToDo: denied listにある場合は取り除く
				continue;
			}

			appendLog(tr("sender: %1 is not allowed").arg(sender.toString()), LogWarn);
			if (ui.deniedList->findItems(sender.toString(), Qt::MatchExactly).count() == 0)
			{
				ui.deniedList->addItem(sender.toString());
				if (ui.notifyOnNewClient->isChecked())
					trayIcon->showMessage(qApp->applicationName(), tr("A new client %1 is found.").arg(sender.toString()), QSystemTrayIcon::Information, 5000);
			}
			continue;
		}

		if (!validateData(data.data(), data.size()))
		{
			appendLog(tr("invalid packet"), LogError);
			return;
		}

		if (ui.disableAllEvents->isChecked())	return;

		for (int i = 0; i != data.size(); ++i)
		{
			BYTE operation = static_cast<BYTE>(data[i]);
			switch (operation)
			{
				case WR_KEY_PRESS:
				case WR_KEY_RELEASE:
				{
					unsigned char key = data[++i];
										if (ui.disableKeyboardEvents->isChecked())  break;

					keybd_event(key, 0, (operation == WR_KEY_RELEASE ? KEYEVENTF_KEYUP : 0), 0);
					appendLog(QString("%1:%2: key press/release: %3").arg(sender.toString()).arg(senderPort).arg(key));
					break;
				}

				case WR_KEY_CLICK:
				{
					unsigned char key = data[++i];
					if (ui.disableKeyboardEvents->isChecked())  break;

					keybd_event(key, 0, 0, 0);
					Sleep(ui.clickDelay->value());
					keybd_event(key, 0, KEYEVENTF_KEYUP, 0);
					appendLog(QString("%1:%2: key click: %3").arg(sender.toString()).arg(senderPort).arg(key));
					break;
				}

				case WR_MOUSE_MOVE_ABSOLUTE:
				{
					unsigned char x = data[++i];
					unsigned char y = data[++i];
					if (ui.disableMouseEvents->isChecked())     break;

					// 画面の座標は左端0-65535右端
					mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, static_cast<int>(65535 * ((double)x / UCHAR_MAX)), static_cast<int>(65535 * ((double)y / UCHAR_MAX)), 0, 0);
					appendLog(QString("%1:%2: ABS_BYTE(%3,%4)").arg(sender.toString()).arg(senderPort).arg(static_cast<BYTE>(x)).arg(static_cast<BYTE>(y)));
					break;
				}

				case WR_MOUSE_MOVE_ABSOLUTE_WORD:
				{
					unsigned short x = ntohs(data[++i] | (data[++i] << 8));
					unsigned short y = ntohs(data[++i] | (data[++i] << 8));
					if (ui.disableMouseEvents->isChecked())     break;

					// 画面の座標は左端0-65535右端
					mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0);
					appendLog(QString("%1:%2: ABS_WORD(%3,%4)").arg(sender.toString()).arg(senderPort).arg(x).arg(y));
					break;
				}

				case WR_MOUSE_MOVE_RELATIVE:
				{
					signed char x = data[++i];
					signed char y = data[++i];
					if (ui.disableMouseEvents->isChecked())     break;

					mouse_event(MOUSEEVENTF_MOVE, static_cast<int>(x * ui.mouseAccel->value()), static_cast<int>(y * ui.mouseAccel->value()), 0, 0);
					appendLog(QString("%1:%2: REL(%3,%4)").arg(sender.toString()).arg(senderPort).arg(static_cast<signed>(x)).arg(static_cast<signed>(y)));
					break;
				}


				case WR_MOUSE_BUTTON_PRESS:
				{
					unsigned char f = data[++i];
					int flag = (f & WR_MOUSE_LEFT_BUTTON ? MOUSEEVENTF_LEFTDOWN : 0) | (f & WR_MOUSE_RIGHT_BUTTON ? MOUSEEVENTF_RIGHTDOWN : 0) | (f & WR_MOUSE_MIDDLE_BUTTON ? MOUSEEVENTF_MIDDLEDOWN : 0);
					if (ui.disableMouseEvents->isChecked())     break;

					mouse_event(flag, 0, 0, 0, 0);
					appendLog(QString("%1:%2: mouse button press").arg(sender.toString()).arg(senderPort));
					break;
				}

				case WR_MOUSE_BUTTON_RELEASE:
				{
					unsigned char f = data[++i];
					int flag = (f & WR_MOUSE_LEFT_BUTTON ? MOUSEEVENTF_LEFTUP : 0) | (f & WR_MOUSE_RIGHT_BUTTON ? MOUSEEVENTF_RIGHTUP : 0) | (f & WR_MOUSE_MIDDLE_BUTTON ? MOUSEEVENTF_MIDDLEUP : 0);
					if (ui.disableMouseEvents->isChecked())     break;

					mouse_event(flag, 0, 0, 0, 0);
					appendLog(QString("%1:%2: mouse button release").arg(sender.toString()).arg(senderPort));
					break;
				}

				case WR_MOUSE_BUTTON_CLICK:
				{
					unsigned char f = data[++i];
					int pressFlag = (f & WR_MOUSE_LEFT_BUTTON ? MOUSEEVENTF_LEFTDOWN : 0) | (f & WR_MOUSE_RIGHT_BUTTON ? MOUSEEVENTF_RIGHTDOWN : 0) | (f & WR_MOUSE_MIDDLE_BUTTON ? MOUSEEVENTF_MIDDLEDOWN : 0);
					int releaseFlag = (f & WR_MOUSE_LEFT_BUTTON ? MOUSEEVENTF_LEFTUP : 0) | (f & WR_MOUSE_RIGHT_BUTTON ? MOUSEEVENTF_RIGHTUP : 0) | (f & WR_MOUSE_MIDDLE_BUTTON ? MOUSEEVENTF_MIDDLEUP : 0);
					if (ui.disableMouseEvents->isChecked())     break;

					mouse_event(pressFlag, 0, 0, 0, 0);
					Sleep(ui.clickDelay->value());
					mouse_event(releaseFlag, 0, 0, 0, 0);
					appendLog(QString("%1:%2: mouse button click").arg(sender.toString()).arg(senderPort));
					break;
				}

				case WR_MOUSE_WHEEL:
				{
					signed char wheel = data[++i];
					int flag = MOUSEEVENTF_WHEEL;
					if (ui.disableMouseEvents->isChecked())	break;

					mouse_event(flag, 0, 0, static_cast<int>(wheel * WHEEL_DELTA / 2.0), 0);
					appendLog(QString("%1:%2: wheel %3").arg(sender.toString()).arg(senderPort).arg(static_cast<int>(wheel)));
					break;
				}

				case WR_KEY_PRESS_QT:
				case WR_KEY_RELEASE_QT:
				case WR_KEY_CLICK_QT:
				{
					unsigned int key = ntohl(data[++i] | data[++i] << 8 | data[++i] << 16 | data[++i] << 24);
					if (ui.disableKeyboardEvents->isChecked())  break;

					KeyCombination vks;
					switch (ui.keyboardType->currentIndex())
					{
						case 0:	// U.S. 101/102
							vks = standardKeyMap[key];	break;
						case 1:	// Japanese 106/109
							vks = japaneseKeyMap[key];	break;
						default:	break;
					}

					switch (operation)
					{
						case WR_KEY_PRESS_QT:
						case WR_KEY_CLICK_QT:
							for (int i = 0; i != vks.size(); ++i)
							{
								keybd_event(vks[i], 0, 0, 0);
								Sleep(ui.clickDelay->value());
							}
							if (operation != WR_KEY_CLICK_QT)	break;	// CLICKの時はReleaseも実行
						case WR_KEY_RELEASE_QT:
							for (int i = (vks.size() - 1); 0 <= i; --i)
							{
								keybd_event(vks[i], 0, KEYEVENTF_KEYUP, 0);
								Sleep(ui.clickDelay->value());
							}
							break;
						default:	break;
					}
					appendLog(QString("%1:%2: Qt key press/release: %3").arg(sender.toString()).arg(senderPort).arg(key));
					break;
				}

				case WR_TEXT:
				{
					QString s = QString::fromUtf8(data.constData() + 1, data.size() - 1);
					i = data.size() - 1;
					if (ui.disableTextInput->isChecked())	break;

					QClipboard *clipboard = QApplication::clipboard();
					QString prevText = clipboard->text();
					clipboard->setText(s);
					keybd_event(VK_CONTROL, 0, 0, 0);
					keybd_event('V', 0, 0, 0);
					Sleep(ui.clickDelay->value());
					keybd_event('V', 0, KEYEVENTF_KEYUP, 0);
					keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
					Sleep(ui.clickDelay->value());	// temporary using click delay. Sleep入れないと復元されない時がある
					clipboard->setText(prevText);	// 画像等は復元されない
					appendLog(QString("%1:%2: text %3").arg(sender.toString()).arg(senderPort).arg(s));
					break;
				}

				default:
					appendLog(QString("%1:%2: not supported: %3").arg(sender.toString()).arg(senderPort).arg(static_cast<int>(*data)));
					break;
			}
		}
	}
}

using namespace Qt;

void WinRemocon::setupKeyMaps()
{
/*
Virtual Key	US	Japanese
VK_OEM_1	;
VK_OEM_2	/
VK_OEM_3	`
VK_OEM_4	[
VK_OEM_5	\
VK_OEM_6	]
VK_OEM_7	'
VK_OEM_PLUS	=
VK_OEM_MINUS	-

VK_OEM_1	:
VK_OEM_PLUS	;
VK_OEM_MINUS	-
VK_OEM_2	/
VK_OEM_3	@
VK_OEM_4	[
VK_OEM_5	\
VK_OEM_6	]
VK_OEM_7	^	right of right of 0
VK_OEM_8	nothing
VK_OEM_102	\
VK_OEM_AUTO	半角/全角

!"#$%&'()=~|
`{
+*}
<>?_
*/
	// U.S. 101/102
	standardKeyMap.insert(Key_Escape, KeyCombination() << VK_ESCAPE);
	standardKeyMap.insert(Key_Tab, KeyCombination() << VK_TAB);
	standardKeyMap.insert(Key_Backtab, KeyCombination() << VK_SHIFT << VK_TAB);
	standardKeyMap.insert(Key_Backspace, KeyCombination() << VK_BACK);
	standardKeyMap.insert(Key_Return, KeyCombination() << VK_RETURN);
	standardKeyMap.insert(Key_Enter, KeyCombination() << VK_RETURN);
	standardKeyMap.insert(Key_Insert, KeyCombination() << VK_INSERT);
	standardKeyMap.insert(Key_Delete, KeyCombination() << VK_DELETE);
	standardKeyMap.insert(Key_Pause, KeyCombination() << VK_PAUSE);
	standardKeyMap.insert(Key_Print, KeyCombination() << VK_PRINT);
/*
	standardKeyMap.insert(Key_SysReq, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_Clear, KeyCombination() << VK_CLEAR);
	standardKeyMap.insert(Key_Home, KeyCombination() << VK_HOME);
	standardKeyMap.insert(Key_End, KeyCombination() << VK_END);
	standardKeyMap.insert(Key_Left, KeyCombination() << VK_LEFT);
	standardKeyMap.insert(Key_Up, KeyCombination() << VK_UP);
	standardKeyMap.insert(Key_Right, KeyCombination() << VK_RIGHT);
	standardKeyMap.insert(Key_Down, KeyCombination() << VK_DOWN);
	standardKeyMap.insert(Key_PageUp, KeyCombination() << VK_PRIOR);
	standardKeyMap.insert(Key_PageDown, KeyCombination() << VK_NEXT);
	standardKeyMap.insert(Key_Shift, KeyCombination() << VK_SHIFT);
	standardKeyMap.insert(Key_Control, KeyCombination() << VK_CONTROL);
	standardKeyMap.insert(Key_Meta, KeyCombination() << VK_LWIN);
	standardKeyMap.insert(Key_Alt, KeyCombination() << VK_MENU);
	standardKeyMap.insert(Key_AltGr, KeyCombination() << VK_CONTROL << VK_MENU);
	standardKeyMap.insert(Key_CapsLock, KeyCombination() << VK_CAPITAL);
	standardKeyMap.insert(Key_NumLock, KeyCombination() << VK_NUMLOCK);
	standardKeyMap.insert(Key_ScrollLock, KeyCombination() << VK_SCROLL);
	standardKeyMap.insert(Key_F1, KeyCombination() << VK_F1);
	standardKeyMap.insert(Key_F2, KeyCombination() << VK_F2);
	standardKeyMap.insert(Key_F3, KeyCombination() << VK_F3);
	standardKeyMap.insert(Key_F4, KeyCombination() << VK_F4);
	standardKeyMap.insert(Key_F5, KeyCombination() << VK_F5);
	standardKeyMap.insert(Key_F6, KeyCombination() << VK_F6);
	standardKeyMap.insert(Key_F7, KeyCombination() << VK_F7);
	standardKeyMap.insert(Key_F8, KeyCombination() << VK_F8);
	standardKeyMap.insert(Key_F9, KeyCombination() << VK_F9);
	standardKeyMap.insert(Key_F10, KeyCombination() << VK_F10);
	standardKeyMap.insert(Key_F11, KeyCombination() << VK_F11);
	standardKeyMap.insert(Key_F12, KeyCombination() << VK_F12);
	standardKeyMap.insert(Key_F13, KeyCombination() << VK_F13);
	standardKeyMap.insert(Key_F14, KeyCombination() << VK_F14);
	standardKeyMap.insert(Key_F15, KeyCombination() << VK_F15);
	standardKeyMap.insert(Key_F16, KeyCombination() << VK_F16);
	standardKeyMap.insert(Key_F17, KeyCombination() << VK_F17);
	standardKeyMap.insert(Key_F18, KeyCombination() << VK_F18);
	standardKeyMap.insert(Key_F19, KeyCombination() << VK_F19);
	standardKeyMap.insert(Key_F20, KeyCombination() << VK_F20);
	standardKeyMap.insert(Key_F21, KeyCombination() << VK_F21);
	standardKeyMap.insert(Key_F22, KeyCombination() << VK_F22);
	standardKeyMap.insert(Key_F23, KeyCombination() << VK_F23);
	standardKeyMap.insert(Key_F24, KeyCombination() << VK_F24);
/*
	standardKeyMap.insert(Key_Super_L, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Super_R, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_Menu, KeyCombination() << VK_APPS);
/*
	standardKeyMap.insert(Key_Hyper_L, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Hyper_R, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_Help, KeyCombination() << VK_HELP);
/*
	standardKeyMap.insert(Key_Direction_L, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Direction_R, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_Space, KeyCombination() << VK_SPACE);
/*
	standardKeyMap.insert(Key_Any, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_Exclam, KeyCombination() << VK_SHIFT << '1');	// !
	standardKeyMap.insert(Key_QuoteDbl, KeyCombination() << VK_SHIFT << VK_OEM_7);	// "
	standardKeyMap.insert(Key_NumberSign, KeyCombination() << VK_SHIFT << '3');	// #
	standardKeyMap.insert(Key_Dollar, KeyCombination() << VK_SHIFT << '4');	// $
	standardKeyMap.insert(Key_Percent, KeyCombination() << VK_SHIFT << '5');	// %
	standardKeyMap.insert(Key_Ampersand, KeyCombination() << VK_SHIFT << '7');	// &
	standardKeyMap.insert(Key_Apostrophe, KeyCombination() << VK_OEM_7);	// '
	standardKeyMap.insert(Key_ParenLeft, KeyCombination() << VK_SHIFT << '9');	// (
	standardKeyMap.insert(Key_ParenRight, KeyCombination() << VK_SHIFT << '0');	// )
	standardKeyMap.insert(Key_Asterisk, KeyCombination() << VK_SHIFT << '8');	// *
	standardKeyMap.insert(Key_Plus, KeyCombination() << VK_SHIFT << VK_OEM_PLUS);	// +
	standardKeyMap.insert(Key_Comma, KeyCombination() << VK_OEM_COMMA);	// ,
	standardKeyMap.insert(Key_Minus, KeyCombination() << VK_OEM_MINUS);	// -
	standardKeyMap.insert(Key_Period, KeyCombination() << VK_OEM_PERIOD);	// .
	standardKeyMap.insert(Key_Slash, KeyCombination() << VK_OEM_2);	// /
	standardKeyMap.insert(Key_0, KeyCombination() << '0');
	standardKeyMap.insert(Key_1, KeyCombination() << '1');
	standardKeyMap.insert(Key_2, KeyCombination() << '2');
	standardKeyMap.insert(Key_3, KeyCombination() << '3');
	standardKeyMap.insert(Key_4, KeyCombination() << '4');
	standardKeyMap.insert(Key_5, KeyCombination() << '5');
	standardKeyMap.insert(Key_6, KeyCombination() << '6');
	standardKeyMap.insert(Key_7, KeyCombination() << '7');
	standardKeyMap.insert(Key_8, KeyCombination() << '8');
	standardKeyMap.insert(Key_9, KeyCombination() << '9');
	standardKeyMap.insert(Key_Colon, KeyCombination() << VK_SHIFT << VK_OEM_1);	// :
	standardKeyMap.insert(Key_Semicolon, KeyCombination() << VK_OEM_1);	// ;
	standardKeyMap.insert(Key_Less, KeyCombination() << VK_SHIFT << VK_OEM_COMMA);	// <
	standardKeyMap.insert(Key_Equal, KeyCombination() << VK_OEM_PLUS);	// =
	standardKeyMap.insert(Key_Greater, KeyCombination() << VK_SHIFT << VK_OEM_PERIOD);	// >
	standardKeyMap.insert(Key_Question, KeyCombination() << VK_SHIFT << VK_OEM_2);	// ?
	standardKeyMap.insert(Key_At, KeyCombination() << VK_SHIFT << '2');	// @
	standardKeyMap.insert(Key_A, KeyCombination() << 'A');
	standardKeyMap.insert(Key_B, KeyCombination() << 'B');
	standardKeyMap.insert(Key_C, KeyCombination() << 'C');
	standardKeyMap.insert(Key_D, KeyCombination() << 'D');
	standardKeyMap.insert(Key_E, KeyCombination() << 'E');
	standardKeyMap.insert(Key_F, KeyCombination() << 'F');
	standardKeyMap.insert(Key_G, KeyCombination() << 'G');
	standardKeyMap.insert(Key_H, KeyCombination() << 'H');
	standardKeyMap.insert(Key_I, KeyCombination() << 'I');
	standardKeyMap.insert(Key_J, KeyCombination() << 'J');
	standardKeyMap.insert(Key_K, KeyCombination() << 'K');
	standardKeyMap.insert(Key_L, KeyCombination() << 'L');
	standardKeyMap.insert(Key_M, KeyCombination() << 'M');
	standardKeyMap.insert(Key_N, KeyCombination() << 'N');
	standardKeyMap.insert(Key_O, KeyCombination() << 'O');
	standardKeyMap.insert(Key_P, KeyCombination() << 'P');
	standardKeyMap.insert(Key_Q, KeyCombination() << 'Q');
	standardKeyMap.insert(Key_R, KeyCombination() << 'R');
	standardKeyMap.insert(Key_S, KeyCombination() << 'S');
	standardKeyMap.insert(Key_T, KeyCombination() << 'T');
	standardKeyMap.insert(Key_U, KeyCombination() << 'U');
	standardKeyMap.insert(Key_V, KeyCombination() << 'V');
	standardKeyMap.insert(Key_W, KeyCombination() << 'W');
	standardKeyMap.insert(Key_X, KeyCombination() << 'X');
	standardKeyMap.insert(Key_Y, KeyCombination() << 'Y');
	standardKeyMap.insert(Key_Z, KeyCombination() << 'Z');
	standardKeyMap.insert(Key_BracketLeft, KeyCombination() << VK_OEM_4);	// [
	standardKeyMap.insert(Key_Backslash, KeyCombination() << VK_OEM_5);	// '\\'
	standardKeyMap.insert(Key_BracketRight, KeyCombination() << VK_OEM_6);	// ]
	standardKeyMap.insert(Key_AsciiCircum, KeyCombination() << VK_SHIFT << '6');	// ^
	standardKeyMap.insert(Key_Underscore, KeyCombination() << VK_SHIFT << VK_OEM_MINUS);	// _
	standardKeyMap.insert(Key_QuoteLeft, KeyCombination() << VK_OEM_3);	// `
	standardKeyMap.insert(Key_BraceLeft, KeyCombination() << VK_SHIFT << VK_OEM_4);	// {
	standardKeyMap.insert(Key_Bar, KeyCombination() << VK_SHIFT << VK_OEM_5);	// |
	standardKeyMap.insert(Key_BraceRight, KeyCombination() << VK_SHIFT << VK_OEM_6);	// }
	standardKeyMap.insert(Key_AsciiTilde, KeyCombination() << VK_SHIFT << VK_OEM_3);	// ~
/*
	standardKeyMap.insert(Key_nobreakspace, KeyCombination() << VK_);
	standardKeyMap.insert(Key_exclamdown, KeyCombination() << VK_);
	standardKeyMap.insert(Key_cent, KeyCombination() << VK_);
	standardKeyMap.insert(Key_sterling, KeyCombination() << VK_);
	standardKeyMap.insert(Key_currency, KeyCombination() << VK_);
	standardKeyMap.insert(Key_yen, KeyCombination() << VK_);
	standardKeyMap.insert(Key_brokenbar, KeyCombination() << VK_);
	standardKeyMap.insert(Key_section, KeyCombination() << VK_);
	standardKeyMap.insert(Key_diaeresis, KeyCombination() << VK_);
	standardKeyMap.insert(Key_copyright, KeyCombination() << VK_);
	standardKeyMap.insert(Key_ordfeminine, KeyCombination() << VK_);
	standardKeyMap.insert(Key_guillemotleft, KeyCombination() << VK_);
	standardKeyMap.insert(Key_notsign, KeyCombination() << VK_);
	standardKeyMap.insert(Key_hyphen, KeyCombination() << VK_);
	standardKeyMap.insert(Key_registered, KeyCombination() << VK_);
	standardKeyMap.insert(Key_macron, KeyCombination() << VK_);
	standardKeyMap.insert(Key_degree, KeyCombination() << VK_);
	standardKeyMap.insert(Key_plusminus, KeyCombination() << VK_);
	standardKeyMap.insert(Key_twosuperior, KeyCombination() << VK_);
	standardKeyMap.insert(Key_threesuperior, KeyCombination() << VK_);
	standardKeyMap.insert(Key_acute, KeyCombination() << VK_);
	standardKeyMap.insert(Key_mu, KeyCombination() << VK_);
	standardKeyMap.insert(Key_paragraph, KeyCombination() << VK_);
	standardKeyMap.insert(Key_periodcentered, KeyCombination() << VK_);
	standardKeyMap.insert(Key_cedilla, KeyCombination() << VK_);
	standardKeyMap.insert(Key_onesuperior, KeyCombination() << VK_);
	standardKeyMap.insert(Key_masculine, KeyCombination() << VK_);
	standardKeyMap.insert(Key_guillemotright, KeyCombination() << VK_);
	standardKeyMap.insert(Key_onequarter, KeyCombination() << VK_);
	standardKeyMap.insert(Key_onehalf, KeyCombination() << VK_);
	standardKeyMap.insert(Key_threequarters, KeyCombination() << VK_);
	standardKeyMap.insert(Key_questiondown, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Multi_key, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Codeinput, KeyCombination() << VK_);
	standardKeyMap.insert(Key_SingleCandidate, KeyCombination() << VK_);
	standardKeyMap.insert(Key_MultipleCandidate, KeyCombination() << VK_);
	standardKeyMap.insert(Key_PreviousCandidate, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Mode_switch, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Kanji, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Muhenkan, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Henkan, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Romaji, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Hiragana, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Katakana, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Hiragana_Katakana, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Zenkaku, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Hankaku, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_Zenkaku_Hankaku, KeyCombination() << VK_OEM_3);
/*
	standardKeyMap.insert(Key_Touroku, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Massyo, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Kana_Lock, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Kana_Shift, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Eisu_Shift, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Eisu_toggle, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_Back, KeyCombination() << VK_BROWSER_BACK);
	standardKeyMap.insert(Key_Forward, KeyCombination() << VK_BROWSER_FORWARD);
	standardKeyMap.insert(Key_Stop, KeyCombination() << VK_BROWSER_STOP);
	standardKeyMap.insert(Key_Refresh, KeyCombination() << VK_BROWSER_REFRESH);
	standardKeyMap.insert(Key_VolumeDown, KeyCombination() << VK_VOLUME_DOWN);
	standardKeyMap.insert(Key_VolumeMute, KeyCombination() << VK_VOLUME_MUTE);
	standardKeyMap.insert(Key_VolumeUp, KeyCombination() << VK_VOLUME_UP);
/*
	standardKeyMap.insert(Key_BassBoost, KeyCombination() << VK_);
	standardKeyMap.insert(Key_BassUp, KeyCombination() << VK_);
	standardKeyMap.insert(Key_BassDown, KeyCombination() << VK_);
	standardKeyMap.insert(Key_TrebleUp, KeyCombination() << VK_);
	standardKeyMap.insert(Key_TrebleDown, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_MediaPlay, KeyCombination() << VK_MEDIA_PLAY_PAUSE);
	standardKeyMap.insert(Key_MediaStop, KeyCombination() << VK_MEDIA_STOP);
	standardKeyMap.insert(Key_MediaPrevious, KeyCombination() << VK_MEDIA_PREV_TRACK);
	standardKeyMap.insert(Key_MediaNext, KeyCombination() << VK_MEDIA_NEXT_TRACK);
/*
	standardKeyMap.insert(Key_MediaRecord, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_HomePage, KeyCombination() << VK_BROWSER_HOME);
	standardKeyMap.insert(Key_Favorites, KeyCombination() << VK_BROWSER_FAVORITES);
	standardKeyMap.insert(Key_Search, KeyCombination() << VK_BROWSER_SEARCH);
/*
	standardKeyMap.insert(Key_Standby, KeyCombination() << VK_);
	standardKeyMap.insert(Key_OpenUrl, KeyCombination() << VK_);
*/
	standardKeyMap.insert(Key_LaunchMail, KeyCombination() << VK_LAUNCH_MAIL);
	standardKeyMap.insert(Key_LaunchMedia, KeyCombination() << VK_LAUNCH_MEDIA_SELECT);
	standardKeyMap.insert(Key_Launch0, KeyCombination() << VK_LAUNCH_APP1);
	standardKeyMap.insert(Key_Launch1, KeyCombination() << VK_LAUNCH_APP2);
/*
	standardKeyMap.insert(Key_Launch2, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Launch3, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Launch4, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Launch5, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Launch6, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Launch7, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Launch8, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Launch9, KeyCombination() << VK_);
	standardKeyMap.insert(Key_LaunchA, KeyCombination() << VK_);
	standardKeyMap.insert(Key_LaunchB, KeyCombination() << VK_);
	standardKeyMap.insert(Key_LaunchC, KeyCombination() << VK_);
	standardKeyMap.insert(Key_LaunchD, KeyCombination() << VK_);
	standardKeyMap.insert(Key_LaunchE, KeyCombination() << VK_);
	standardKeyMap.insert(Key_LaunchF, KeyCombination() << VK_);
	standardKeyMap.insert(Key_MediaLast, KeyCombination() << VK_);
	standardKeyMap.insert(Key_unknown, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Call, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Context1, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Context2, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Context3, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Context4, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Flip, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Hangup, KeyCombination() << VK_);
	standardKeyMap.insert(Key_No, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Select, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Yes, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Execute, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Printer, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Play, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Sleep, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Zoom, KeyCombination() << VK_);
	standardKeyMap.insert(Key_Cancel, KeyCombination() << VK_);
*/
	// standardKeyMap.insert(Key_, KeyCombination() << VK_);


	// Japanese 106/109
	japaneseKeyMap.insert(Key_Escape, KeyCombination() << VK_ESCAPE);
	japaneseKeyMap.insert(Key_Tab, KeyCombination() << VK_TAB);
	japaneseKeyMap.insert(Key_Backtab, KeyCombination() << VK_SHIFT << VK_TAB);
	japaneseKeyMap.insert(Key_Backspace, KeyCombination() << VK_BACK);
	japaneseKeyMap.insert(Key_Return, KeyCombination() << VK_RETURN);
	japaneseKeyMap.insert(Key_Enter, KeyCombination() << VK_RETURN);
	japaneseKeyMap.insert(Key_Insert, KeyCombination() << VK_INSERT);
	japaneseKeyMap.insert(Key_Delete, KeyCombination() << VK_DELETE);
	japaneseKeyMap.insert(Key_Pause, KeyCombination() << VK_PAUSE);
	japaneseKeyMap.insert(Key_Print, KeyCombination() << VK_PRINT);
/*
	japaneseKeyMap.insert(Key_SysReq, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_Clear, KeyCombination() << VK_CLEAR);
	japaneseKeyMap.insert(Key_Home, KeyCombination() << VK_HOME);
	japaneseKeyMap.insert(Key_End, KeyCombination() << VK_END);
	japaneseKeyMap.insert(Key_Left, KeyCombination() << VK_LEFT);
	japaneseKeyMap.insert(Key_Up, KeyCombination() << VK_UP);
	japaneseKeyMap.insert(Key_Right, KeyCombination() << VK_RIGHT);
	japaneseKeyMap.insert(Key_Down, KeyCombination() << VK_DOWN);
	japaneseKeyMap.insert(Key_PageUp, KeyCombination() << VK_PRIOR);
	japaneseKeyMap.insert(Key_PageDown, KeyCombination() << VK_NEXT);
	japaneseKeyMap.insert(Key_Shift, KeyCombination() << VK_SHIFT);
	japaneseKeyMap.insert(Key_Control, KeyCombination() << VK_CONTROL);
	japaneseKeyMap.insert(Key_Meta, KeyCombination() << VK_LWIN);
	japaneseKeyMap.insert(Key_Alt, KeyCombination() << VK_MENU);
	japaneseKeyMap.insert(Key_AltGr, KeyCombination() << VK_CONTROL << VK_MENU);
	japaneseKeyMap.insert(Key_CapsLock, KeyCombination() << VK_CAPITAL);
	japaneseKeyMap.insert(Key_NumLock, KeyCombination() << VK_NUMLOCK);
	japaneseKeyMap.insert(Key_ScrollLock, KeyCombination() << VK_SCROLL);
	japaneseKeyMap.insert(Key_F1, KeyCombination() << VK_F1);
	japaneseKeyMap.insert(Key_F2, KeyCombination() << VK_F2);
	japaneseKeyMap.insert(Key_F3, KeyCombination() << VK_F3);
	japaneseKeyMap.insert(Key_F4, KeyCombination() << VK_F4);
	japaneseKeyMap.insert(Key_F5, KeyCombination() << VK_F5);
	japaneseKeyMap.insert(Key_F6, KeyCombination() << VK_F6);
	japaneseKeyMap.insert(Key_F7, KeyCombination() << VK_F7);
	japaneseKeyMap.insert(Key_F8, KeyCombination() << VK_F8);
	japaneseKeyMap.insert(Key_F9, KeyCombination() << VK_F9);
	japaneseKeyMap.insert(Key_F10, KeyCombination() << VK_F10);
	japaneseKeyMap.insert(Key_F11, KeyCombination() << VK_F11);
	japaneseKeyMap.insert(Key_F12, KeyCombination() << VK_F12);
	japaneseKeyMap.insert(Key_F13, KeyCombination() << VK_F13);
	japaneseKeyMap.insert(Key_F14, KeyCombination() << VK_F14);
	japaneseKeyMap.insert(Key_F15, KeyCombination() << VK_F15);
	japaneseKeyMap.insert(Key_F16, KeyCombination() << VK_F16);
	japaneseKeyMap.insert(Key_F17, KeyCombination() << VK_F17);
	japaneseKeyMap.insert(Key_F18, KeyCombination() << VK_F18);
	japaneseKeyMap.insert(Key_F19, KeyCombination() << VK_F19);
	japaneseKeyMap.insert(Key_F20, KeyCombination() << VK_F20);
	japaneseKeyMap.insert(Key_F21, KeyCombination() << VK_F21);
	japaneseKeyMap.insert(Key_F22, KeyCombination() << VK_F22);
	japaneseKeyMap.insert(Key_F23, KeyCombination() << VK_F23);
	japaneseKeyMap.insert(Key_F24, KeyCombination() << VK_F24);
/*
	japaneseKeyMap.insert(Key_Super_L, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Super_R, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_Menu, KeyCombination() << VK_APPS);
/*
	japaneseKeyMap.insert(Key_Hyper_L, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Hyper_R, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_Help, KeyCombination() << VK_HELP);
/*
	japaneseKeyMap.insert(Key_Direction_L, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Direction_R, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_Space, KeyCombination() << VK_SPACE);
/*
	japaneseKeyMap.insert(Key_Any, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_Exclam, KeyCombination() << VK_SHIFT << '1');	// !
	japaneseKeyMap.insert(Key_QuoteDbl, KeyCombination() << VK_SHIFT << '2');	// "
	japaneseKeyMap.insert(Key_NumberSign, KeyCombination() << VK_SHIFT << '3');	// #
	japaneseKeyMap.insert(Key_Dollar, KeyCombination() << VK_SHIFT << '4');	// $
	japaneseKeyMap.insert(Key_Percent, KeyCombination() << VK_SHIFT << '5');	// %
	japaneseKeyMap.insert(Key_Ampersand, KeyCombination() << VK_SHIFT << '6');	// &
	japaneseKeyMap.insert(Key_Apostrophe, KeyCombination() << VK_SHIFT << '7');	// '
	japaneseKeyMap.insert(Key_ParenLeft, KeyCombination() << VK_SHIFT << '8');	// (
	japaneseKeyMap.insert(Key_ParenRight, KeyCombination() << VK_SHIFT << '9');	// )
	japaneseKeyMap.insert(Key_Asterisk, KeyCombination() << VK_SHIFT << VK_OEM_1);	// *
	japaneseKeyMap.insert(Key_Plus, KeyCombination() << VK_SHIFT << VK_OEM_PLUS);	// +
	japaneseKeyMap.insert(Key_Comma, KeyCombination() << VK_OEM_COMMA);	// ,
	japaneseKeyMap.insert(Key_Minus, KeyCombination() << VK_OEM_MINUS);	// -
	japaneseKeyMap.insert(Key_Period, KeyCombination() << VK_OEM_PERIOD);	// .
	japaneseKeyMap.insert(Key_Slash, KeyCombination() << VK_OEM_2);	// /
	japaneseKeyMap.insert(Key_0, KeyCombination() << '0');
	japaneseKeyMap.insert(Key_1, KeyCombination() << '1');
	japaneseKeyMap.insert(Key_2, KeyCombination() << '2');
	japaneseKeyMap.insert(Key_3, KeyCombination() << '3');
	japaneseKeyMap.insert(Key_4, KeyCombination() << '4');
	japaneseKeyMap.insert(Key_5, KeyCombination() << '5');
	japaneseKeyMap.insert(Key_6, KeyCombination() << '6');
	japaneseKeyMap.insert(Key_7, KeyCombination() << '7');
	japaneseKeyMap.insert(Key_8, KeyCombination() << '8');
	japaneseKeyMap.insert(Key_9, KeyCombination() << '9');
	japaneseKeyMap.insert(Key_Colon, KeyCombination() << VK_OEM_1);	// :
	japaneseKeyMap.insert(Key_Semicolon, KeyCombination() << VK_OEM_PLUS);	// ;
	japaneseKeyMap.insert(Key_Less, KeyCombination() << VK_SHIFT << VK_OEM_COMMA);	// <
	japaneseKeyMap.insert(Key_Equal, KeyCombination() << VK_SHIFT << VK_OEM_MINUS);	// =
	japaneseKeyMap.insert(Key_Greater, KeyCombination() << VK_SHIFT << VK_OEM_PERIOD);	// >
	japaneseKeyMap.insert(Key_Question, KeyCombination() << VK_SHIFT << VK_OEM_2);	// ?
	japaneseKeyMap.insert(Key_At, KeyCombination() << VK_OEM_3);	// @
	japaneseKeyMap.insert(Key_A, KeyCombination() << 'A');
	japaneseKeyMap.insert(Key_B, KeyCombination() << 'B');
	japaneseKeyMap.insert(Key_C, KeyCombination() << 'C');
	japaneseKeyMap.insert(Key_D, KeyCombination() << 'D');
	japaneseKeyMap.insert(Key_E, KeyCombination() << 'E');
	japaneseKeyMap.insert(Key_F, KeyCombination() << 'F');
	japaneseKeyMap.insert(Key_G, KeyCombination() << 'G');
	japaneseKeyMap.insert(Key_H, KeyCombination() << 'H');
	japaneseKeyMap.insert(Key_I, KeyCombination() << 'I');
	japaneseKeyMap.insert(Key_J, KeyCombination() << 'J');
	japaneseKeyMap.insert(Key_K, KeyCombination() << 'K');
	japaneseKeyMap.insert(Key_L, KeyCombination() << 'L');
	japaneseKeyMap.insert(Key_M, KeyCombination() << 'M');
	japaneseKeyMap.insert(Key_N, KeyCombination() << 'N');
	japaneseKeyMap.insert(Key_O, KeyCombination() << 'O');
	japaneseKeyMap.insert(Key_P, KeyCombination() << 'P');
	japaneseKeyMap.insert(Key_Q, KeyCombination() << 'Q');
	japaneseKeyMap.insert(Key_R, KeyCombination() << 'R');
	japaneseKeyMap.insert(Key_S, KeyCombination() << 'S');
	japaneseKeyMap.insert(Key_T, KeyCombination() << 'T');
	japaneseKeyMap.insert(Key_U, KeyCombination() << 'U');
	japaneseKeyMap.insert(Key_V, KeyCombination() << 'V');
	japaneseKeyMap.insert(Key_W, KeyCombination() << 'W');
	japaneseKeyMap.insert(Key_X, KeyCombination() << 'X');
	japaneseKeyMap.insert(Key_Y, KeyCombination() << 'Y');
	japaneseKeyMap.insert(Key_Z, KeyCombination() << 'Z');
	japaneseKeyMap.insert(Key_BracketLeft, KeyCombination() << VK_OEM_4);	// [
	japaneseKeyMap.insert(Key_Backslash, KeyCombination() << VK_OEM_5);	// '\\'
	japaneseKeyMap.insert(Key_BracketRight, KeyCombination() << VK_OEM_6);	// ]
	japaneseKeyMap.insert(Key_AsciiCircum, KeyCombination() << VK_OEM_7);	// ^
	japaneseKeyMap.insert(Key_Underscore, KeyCombination() << VK_SHIFT << VK_OEM_102);	// _
	japaneseKeyMap.insert(Key_QuoteLeft, KeyCombination() << VK_SHIFT << VK_OEM_3);	// `
	japaneseKeyMap.insert(Key_BraceLeft, KeyCombination() << VK_SHIFT << VK_OEM_4);	// {
	japaneseKeyMap.insert(Key_Bar, KeyCombination() << VK_SHIFT << VK_OEM_5);	// |
	japaneseKeyMap.insert(Key_BraceRight, KeyCombination() << VK_SHIFT << VK_OEM_6);	// }
	japaneseKeyMap.insert(Key_AsciiTilde, KeyCombination() << VK_SHIFT << VK_OEM_7);	// ~
/*
	japaneseKeyMap.insert(Key_nobreakspace, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_exclamdown, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_cent, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_sterling, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_currency, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_yen, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_brokenbar, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_section, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_diaeresis, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_copyright, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_ordfeminine, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_guillemotleft, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_notsign, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_hyphen, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_registered, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_macron, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_degree, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_plusminus, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_twosuperior, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_threesuperior, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_acute, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_mu, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_paragraph, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_periodcentered, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_cedilla, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_onesuperior, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_masculine, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_guillemotright, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_onequarter, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_onehalf, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_threequarters, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_questiondown, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Multi_key, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Codeinput, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_SingleCandidate, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_MultipleCandidate, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_PreviousCandidate, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Mode_switch, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Kanji, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Muhenkan, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Henkan, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Romaji, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Hiragana, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Katakana, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Hiragana_Katakana, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Zenkaku, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Hankaku, KeyCombination() << VK_);
*/
		japaneseKeyMap.insert(Key_Zenkaku_Hankaku, KeyCombination() << 0xf3);   // VK_OEM_AUTO
/*
	japaneseKeyMap.insert(Key_Touroku, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Massyo, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Kana_Lock, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Kana_Shift, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Eisu_Shift, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Eisu_toggle, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_Back, KeyCombination() << VK_BROWSER_BACK);
	japaneseKeyMap.insert(Key_Forward, KeyCombination() << VK_BROWSER_FORWARD);
	japaneseKeyMap.insert(Key_Stop, KeyCombination() << VK_BROWSER_STOP);
	japaneseKeyMap.insert(Key_Refresh, KeyCombination() << VK_BROWSER_REFRESH);
	japaneseKeyMap.insert(Key_VolumeDown, KeyCombination() << VK_VOLUME_DOWN);
	japaneseKeyMap.insert(Key_VolumeMute, KeyCombination() << VK_VOLUME_MUTE);
	japaneseKeyMap.insert(Key_VolumeUp, KeyCombination() << VK_VOLUME_UP);
/*
	japaneseKeyMap.insert(Key_BassBoost, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_BassUp, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_BassDown, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_TrebleUp, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_TrebleDown, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_MediaPlay, KeyCombination() << VK_MEDIA_PLAY_PAUSE);
	japaneseKeyMap.insert(Key_MediaStop, KeyCombination() << VK_MEDIA_STOP);
	japaneseKeyMap.insert(Key_MediaPrevious, KeyCombination() << VK_MEDIA_PREV_TRACK);
	japaneseKeyMap.insert(Key_MediaNext, KeyCombination() << VK_MEDIA_NEXT_TRACK);
/*
	japaneseKeyMap.insert(Key_MediaRecord, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_HomePage, KeyCombination() << VK_BROWSER_HOME);
	japaneseKeyMap.insert(Key_Favorites, KeyCombination() << VK_BROWSER_FAVORITES);
	japaneseKeyMap.insert(Key_Search, KeyCombination() << VK_BROWSER_SEARCH);
/*
	japaneseKeyMap.insert(Key_Standby, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_OpenUrl, KeyCombination() << VK_);
*/
	japaneseKeyMap.insert(Key_LaunchMail, KeyCombination() << VK_LAUNCH_MAIL);
	japaneseKeyMap.insert(Key_LaunchMedia, KeyCombination() << VK_LAUNCH_MEDIA_SELECT);
	japaneseKeyMap.insert(Key_Launch0, KeyCombination() << VK_LAUNCH_APP1);
	japaneseKeyMap.insert(Key_Launch1, KeyCombination() << VK_LAUNCH_APP2);
/*
	japaneseKeyMap.insert(Key_Launch2, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Launch3, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Launch4, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Launch5, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Launch6, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Launch7, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Launch8, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Launch9, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_LaunchA, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_LaunchB, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_LaunchC, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_LaunchD, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_LaunchE, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_LaunchF, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_MediaLast, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_unknown, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Call, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Context1, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Context2, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Context3, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Context4, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Flip, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Hangup, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_No, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Select, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Yes, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Execute, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Printer, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Play, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Sleep, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Zoom, KeyCombination() << VK_);
	japaneseKeyMap.insert(Key_Cancel, KeyCombination() << VK_);
*/
}
